package vn.mahjonggame.game.request;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;

import org.apache.log4j.Logger;

import vn.mahjonggame.game.Mahjong;
import vn.mahjonggame.game.MahjongExtension;
import vn.mahjonggame.metadata.ConfigObject;
import vn.mahjonggame.metadata.GameActionType;
import vn.mahjonggame.metadata.MatchState;
import vn.mahjonggame.metadata.Player;
import vn.mahjonggame.metadata.PlayerMode;
import vn.mahjonggame.metadata.Response;
import vn.mahjonggame.metadata.ResponseCode;
import vn.mahjonggame.metadata.MObject;
import vn.mahjonggame.metadata.RoomVarName;
import vn.mahjonggame.metadata.Tile;
import vn.mahjonggame.metadata.UserVarName;
import vn.mahjonggame.platform.PlatformClient;
import vn.mahjonggame.platform.PlatformConfig;
import vn.mahjonggame.platform.ServerMode;
import vn.mahjonggame.util.PropertiesCache;

import com.smartfoxserver.v2.entities.Room;
import com.smartfoxserver.v2.entities.User;
import com.smartfoxserver.v2.entities.data.ISFSObject;
import com.smartfoxserver.v2.entities.data.SFSArray;
import com.smartfoxserver.v2.entities.data.SFSObject;
import com.smartfoxserver.v2.entities.variables.SFSUserVariable;
import com.smartfoxserver.v2.entities.variables.UserVariable;
import com.smartfoxserver.v2.extensions.BaseClientRequestHandler;
import com.smartfoxserver.v2.extensions.ExtensionLogLevel;

public class StartHandler extends BaseClientRequestHandler {
	
	@Override
	public void handleClientRequest(User user, ISFSObject params) {
		
		MahjongExtension ext = (MahjongExtension) getParentExtension();
		Mahjong mahjong = ext.getMahjong();		
		List<Player> players = mahjong.getPlayers();
		List<User> users = user.getLastJoinedRoom().getUserList();
		Player player = mahjong.getPlayerById(user.getId());	
		Logger logger = mahjong.getLogger();
		Room room = getParentExtension().getParentRoom();
		User owner = room.getOwner();
		
		int player_ok = 0;			
		
		/*
		 * TODO remove
		 *
		UserVariable varBalance = new SFSUserVariable(UserVarName.balance.toString(), 9999);
		getApi().setUserVariables(user, Arrays.asList(varBalance));
		
		/*
		 * Remove
		 */
		
		/*
		 * check if roomer is owner. 
		 */
		if(!owner.equals(user))
		{
			logger.info(mahjong.log(room, player, GameActionType.start.toString(), "Owner: " + owner.getName() + "-" + owner.getId()));
			
			return;
		}			
		
		if (ext.getPlayerMode() == PlayerMode.REAL_MODE.ordinal()){
			
			String access_token = user.getVariable(UserVarName.access_token.toString()).getStringValue();
			String room_id = room.getVariable(RoomVarName.room_id.toString()).getStringValue();
			
			SFSArray sfsPlayers = new SFSArray();
			
			for (Iterator<User> iSfsPlayers = users.iterator(); iSfsPlayers.hasNext();) {
				User iSfsPlayer = (User)iSfsPlayers.next();
				sfsPlayers.addUtfString(iSfsPlayer.getVariable(UserVarName.user_id.toString()).getStringValue());
			}			
			
			logger.info(mahjong.log(room, player, GameActionType.start.toString(), "start game_start_room"));
			
			SFSObject sfsResponse = PlatformClient.game_start_room(access_token, room_id, sfsPlayers);
			
			logger.info(mahjong.log(room, player, GameActionType.start.toString(), "sfsResponse: " + sfsResponse));
			
			if(!mahjong.isApiSuccess(sfsResponse)){
				String msg = "StartHandler: Failed in game_start_room API.";
				
				SFSObject response = mahjong.makeResponseMessage(msg);
				
				send(GameActionType.start.toString(), response, users);	
								
				logger.info(mahjong.log(room, player, GameActionType.start.toString(), msg));
				
				return;
			}
			
			ISFSObject apiReponse = sfsResponse.getSFSObject("response");
			
			logger.info(mahjong.log(room, player, GameActionType.start.toString(), "end game_start_room"));
			
			player_ok = apiReponse.getInt("player_ok");
			SFSObject playerStatus = (SFSObject) apiReponse.getSFSObject("players");
			
			boolean ownerStatus = playerStatus.getBool(room.getOwner().getVariable(UserVarName.user_id.toString()).getStringValue());						
			
			if(ownerStatus == false){
				logger.info(mahjong.log(room, player, GameActionType.start.toString(), "ownerStatus: " + ownerStatus));
				
				ext.removeRoom();
				return;
			}
			
			/*
			 * Remove the invalid player
			 */
			for (int i = 0; i < sfsPlayers.size(); i++) {
				String userId = sfsPlayers.getUtfString(i);
				
				if ( playerStatus.getBool(userId) == false) {
					
					logger.info(mahjong.log(room, player, GameActionType.start.toString(), "playerStatus false: " + userId));
					
					User usr = room.getUserByName(userId);
					if (usr != null)
					{
						Player removePlayer = mahjong.getPlayerById(user.getId());
						int userPosition = removePlayer.getPlayerPosition();
						if(mahjong.getPlayers().remove(removePlayer)){							
							ext.getEmptyPosition().add(userPosition);
							getApi().leaveRoom(usr, room);
						}
						else {
							logger.info(mahjong.log(room, player, GameActionType.start.toString(), "removePlayer: " + removePlayer.toString()));							
						}										
					}
				}
			}
		}			
		
		if (player_ok != Mahjong.NUM_OF_PLAYER)
		{			
			//if(isDebug && player_ok < Mahjong.NUM_OF_PLAYER){
			if(player_ok < Mahjong.NUM_OF_PLAYER){
				/*
				 * Add the simulation player if server is in DEBUG MODE
				 */
				List<Integer> emptyPosition = ext.getEmptyPosition();
				
				List<Integer> playerPositions = new ArrayList<Integer>();
				
				for(Iterator<Player> iPlayers = players.iterator(); iPlayers.hasNext();){
					Player iPlayer = iPlayers.next();
					playerPositions.add(iPlayer.getPlayerId());
				}
				
				while(emptyPosition.size() > 0){
					int newPlayerId = mahjong.rollDice();
					
					while(playerPositions.contains(newPlayerId)){
						newPlayerId = mahjong.rollDice();
					}
					
					playerPositions.add(newPlayerId);
					
					Player playerTmp = new Player(newPlayerId, emptyPosition.remove(0), mahjong);
					playerTmp.setDisconnect(true);
					players.add(playerTmp);
				}
			}
//			else {
//				
//				String mesg = "The number of users is not suitable to start the game";				
//				
//				SFSObject response = mahjong.makeResponseMessage(mesg);				
//				
//				send("start", response, user);				
//				logger.info(mesg);			
//				return;
//			}			
		}
		
		ext.setPlayerReady(user);
		
		if(!ext.isAllPlayerReady()){
			String mesg = "At least one user is not ready.";
			
			SFSObject response = mahjong.makeResponseMessage(mesg);
			
			send(GameActionType.start.toString(), response, user);			
			logger.info(mahjong.log(room, player, GameActionType.start.toString(), mesg));
			return;
		}
		
		ext.dealTile();
		
		player.setHasPicked(false);
		
		int size = players.size();		
				
		for(int i = 0; i < size; i++)
		{
			Player playerTmp = players.get(i);
			User iUser = mahjong.getUserByPlayerId(playerTmp.getPlayerId(), users);
			if(iUser == null) continue;
			
			List<Integer> tileIds = new ArrayList<Integer>();
			
			for(Iterator<Tile> iTiles = playerTmp.getLeftTiles().iterator(); iTiles.hasNext();){
				Tile iTile = iTiles.next();
				tileIds.add(iTile.getId());
			}
						
			/*
			 * Send the respond to client
			 */			
			Response.Builder response = new Response.Builder();
			response.dice1(ext.getMahjong().getDice1())
					.dice2(ext.getMahjong().getDice2())
					.dora(ext.getMahjong().getFirstDoraTileId())
					.lefttiles(tileIds);
						
			logger.info(mahjong.log(room, player, GameActionType.start.toString(), playerTmp.toString() + "leftTiles " + tileIds));
			
			List<Integer> tileIdsInOrder = new ArrayList<Integer>();
			tileIdsInOrder.addAll(tileIds);
			Collections.sort(tileIdsInOrder);
			
			response.lefttilesInOrder(tileIdsInOrder);			
						
			logger.info(mahjong.log(room, player, GameActionType.start.toString(), playerTmp.toString() + "lefttilesInOrder " + tileIdsInOrder));
			
			response.turn(player.getPlayerPosition());			
			
			send(GameActionType.start.toString(), response.build().getSFSObject(), iUser);
		}
				
		ext.addAction(user, GameActionType.start.toString());		
		ext.setMatchState(MatchState.PLAYING);
		
		/*
		 * Set turn for the first position (0)
		 */		
		mahjong.setPlayerInTurn(player);
		
		logger.info(mahjong.log(room, player, GameActionType.start.toString(), "MatchState: " + ext.getMatchState()));		
	}
}
